package ar.edu.itba.it.cg.grupo01.impl;

import javax.vecmath.Point3d;
import javax.vecmath.Tuple3d;
import javax.vecmath.Vector3d;

import ar.edu.itba.it.cg.grupo01.api.Ray;

public class RayImpl implements Ray{

	private final static double angleEpsilon = 0.0001;
	private final static double pointEpsilon = 0.0001;

	private Vector3d direction;
	private Point3d origin;

	public RayImpl(Point3d point, Vector3d direction) {
		this.direction = new Vector3d(direction.x,direction.y,direction.z);
		this.direction.normalize();
		this.origin = new Point3d(point.x,point.y,point.z);
	}

	public RayImpl(Point3d initialPoint, Point3d finalPoint) {
		Vector3d newDirection = new Vector3d(finalPoint);
		newDirection.sub(initialPoint);
		this.direction = newDirection;
		this.direction.normalize();
		this.origin = initialPoint;
	}

	@Override
	public Vector3d getDirection() {
		return new Vector3d(direction.x, direction.y, direction.z);
	}

	@Override
	public Point3d getOrigin() {
		return new Point3d(origin.x,origin.y,origin.z);
	}

	public Boolean contains(Tuple3d point) {
		Vector3d testVector = new Vector3d(point);

		if (this.origin.epsilonEquals(point, pointEpsilon)) {
			Point3d anotherRayPoint = new Point3d(this.origin);
			anotherRayPoint.add(this.direction);
			testVector.sub(anotherRayPoint);
		} else {
			testVector.sub(this.origin);
		}

		double angle = this.direction.angle(testVector);

		return Math.abs(angle) < angleEpsilon
				|| Math.abs(angle - Math.PI) < angleEpsilon;

	}
	

	@Override
	public Point3d calculatePoint(double scalar) {
		Point3d intersectionPoint = new Point3d(this.getDirection());
		intersectionPoint.scaleAdd(scalar, this.getOrigin());
		return intersectionPoint;
	}

}
